package logger

import (
	"errors"
	"fmt"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var globalLogger = NewLogger()

type Logger struct {
	*zap.SugaredLogger
	l *zap.Logger
}

func NewLogger() *Logger {
	logger := &Logger{}
	logger.l, _ = zap.NewDevelopment()
	logger.SugaredLogger = logger.l.Sugar()

	return logger
}

func (s *Logger) With(key string, val interface{}) {
	s.SugaredLogger = s.SugaredLogger.With(zap.Field{
		Key:    key,
		Type:   zapcore.StringType,
		String: fmt.Sprint(val),
	})
}

func (s *Logger) Error(val ...interface{}) {
	newVals := []interface{}{"[Logger.Error]"}
	newVals = append(newVals, val...)
	s.SugaredLogger.Error(newVals...)
}

func (s *Logger) Errorf(f string, args ...interface{}) error {
	s.SugaredLogger.Errorf("[Logger.Error] "+f, args...)
	msg := fmt.Sprintf(f, args...)
	return errors.New(msg)
}

func (s *Logger) Exceptionf(f string, args ...interface{}) error {
	s.SugaredLogger.Errorf(f, args...)
	msg := fmt.Sprintf(f, args...)
	return errors.New(msg)
}

func Global() *Logger {
	return globalLogger
}

func Info(args ...interface{}) {
	globalLogger.Info(args...)
}

func Infof(f string, args ...interface{}) {
	globalLogger.Infof(f, args...)
}

func Error(args ...interface{}) {
	globalLogger.Error(args...)
}

func Errorf(f string, args ...interface{}) {
	globalLogger.Errorf(f, args...)
}
